package com.spontaneappnew.activities;

import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import android.app.ActionBar;
import android.app.FragmentTransaction;

import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.spontaneappnew.NavDrawerActivityConfiguration;
import com.spontaneappnew.NavDrawerItem;
import com.spontaneappnew.NavMenuFBHeader;
import com.spontaneappnew.NavMenuItem;
import com.spontaneappnew.Places;
import com.spontaneappnew.R;
import com.spontaneappnew.adapters.NavDrawerAdapter;
import com.spontaneappnew.adapters.PlaceListPagerAdapter;
import com.spontaneappnew.fragments.FBFriendTabFragment;
import com.spontaneappnew.fragments.FBFriendTabFragment.FBFriendsFragmentListHandle;
import com.spontaneappnew.fragments.AllPlacesFragment.fragmentListHandle;

public class HomeActivity extends AbstractNavDrawerActivity 
								implements LocationListener,  fragmentListHandle, FBFriendsFragmentListHandle {
	
	private PlaceListPagerAdapter mPlaceListPagerAdapter;
	private ViewPager mViewPager;
	
	// Global variable to hold the current location
    private Location mCurrentLocation;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // Create the adapter that will return a fragment for each of the three primary sections
        // of the app.
        mPlaceListPagerAdapter = new PlaceListPagerAdapter(getSupportFragmentManager());
        
        // Set up the action bar.
        final ActionBar actionBar = getActionBar();
        // Specify that we will be displaying tabs in the action bar.
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        
        // Set up the ViewPager, attaching the adapter and setting up a listener for when the
        // user swipes between sections.
        mViewPager = (ViewPager) findViewById(R.id.activity_main_pager);
        mViewPager.setAdapter(mPlaceListPagerAdapter);
        ActionBar.TabListener tabListener = new ActionBar.TabListener() {
			
        	@Override
        	public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
        		// When the given tab is selected, switch to the corresponding page in the ViewPager.
        		mViewPager.setCurrentItem(tab.getPosition());
        	}
        	
        	@Override
            public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
            }

            @Override
            public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
            }
            
		};
		
        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                // When swiping between different lists, select the corresponding tab.
                actionBar.setSelectedNavigationItem(position);
            }
        });
        
        // For each of the lists in the app, add a tab to the action bar.
        for (int i = 0; i < mPlaceListPagerAdapter.getCount(); i++) {
            // Create a tab with text corresponding to the page title defined by the adapter.
            // Also specify this Activity object, which implements the TabListener interface, as the
            // listener for when this tab is selected.
            actionBar.addTab(
                    actionBar.newTab()
                            .setText(mPlaceListPagerAdapter.getPageTitle(i))
                            .setTabListener(tabListener));
        }
        
        // Hide all the actionbar icons
        navConf.setIsActionMenuGroupToHideWhenDrawerOpen(true);
        navConf.setActionMenuGroupToHideWhenDrawerOpen(R.id.action_always_visible);
        int[] itemsToHide = {R.id.action_add_new_place};
        navConf.setActionMenuItemsToHideWhenDrawerOpen(itemsToHide);
	}
	
	
	@Override
	protected void onResume() {
		super.onResume();
		mLocationClient.connect();
	}


	@Override
	protected void onPause() {
		// If the client is connected
        if (mLocationClient.isConnected()) 
        	// Disconnecting the client invalidates it.
        	mLocationClient.disconnect();
		super.onPause();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	@Override
    public boolean onOptionsItemSelected(MenuItem item) {
		if(item.getItemId() == R.id.action_refresh){
			if(!mLocationClient.isConnected())
				// connect to LocationServices, when connected get location and reload
				mLocationClient.connect();
			else
				reloadAll();
			return true;
		}else if(item.getItemId() ==  R.id.action_categories){
			Intent intent = new Intent(this, CategoriesActivity.class);
			// send the current location to the categories activity in order to calculate distance in the filtered list
			Bundle bundle = new Bundle();
			if(mCurrentLocation!=null){
				bundle.putDouble("lat", mCurrentLocation.getLatitude());
				bundle.putDouble("lng", mCurrentLocation.getLongitude());
			}
			intent.putExtras(bundle);
			startActivity(intent);
			return true;
		}
		return super.onOptionsItemSelected(item);
	}
	
    @Override
	public void onLocationChanged(Location newLocation) {
    	int currRadius = getCurrRadiusToLoad();
		Places.getInitializedInstance(newLocation, currRadius);
		
		hideProgressCircle();
    }
    
	@Override
    protected void onNavItemSelected(int id) {
		Intent intent = null;
		switch ((int)id) {
        // Home nav button was pressed - just close drawer
        case 101:
            break;
        // My places nav drawer was pressed
        case 102:
            intent = new Intent(this, MyPlacesNew.class);
            break;
        // Settings nav button was pressed
        case 103:
        	intent = new Intent(this, SettingsActivity.class);
            break;
	    }
		if(intent != null)
        	startActivity(intent);
		else
        	super.onNavItemSelected(id);
    }
	
	/*
     * Initialize the nav drawer configurations and returns it to navConf
     */
	@Override
    protected NavDrawerActivityConfiguration getNavDrawerConfiguration() {
        NavDrawerItem[] menu = new NavDrawerItem[] {
        		NavMenuFBHeader.create( 100, "User"),
                NavMenuItem.create(101, "Home", "ic_home", this),
                NavMenuItem.create(102, "My Places", "ic_menu_myplaces", this),
                NavMenuItem.create(103, "Settings", "ic_menu_settings", this),
                NavMenuItem.create(105, "About", "ic_action_about_light", this),
                NavMenuItem.create(107, "Rate Us!", "ic_whats_hot", this),
                NavMenuItem.create(108, "Logout", "ic_menu_logout", this)};
        
        NavDrawerActivityConfiguration navDrawerActivityConfiguration = new NavDrawerActivityConfiguration();
        navDrawerActivityConfiguration.setMainLayout(R.layout.activity_main);
        navDrawerActivityConfiguration.setDrawerLayoutId(R.id.drawer_layout);
        navDrawerActivityConfiguration.setLeftDrawerId(R.id.left_drawer);
        navDrawerActivityConfiguration.setNavItems(menu);
        navDrawerActivityConfiguration.setDrawerShadow(R.drawable.drawer_shadow);       
        navDrawerActivityConfiguration.setDrawerOpenDesc(R.string.drawer_open);
        navDrawerActivityConfiguration.setDrawerCloseDesc(R.string.drawer_close);
        navDrawerActivityConfiguration.setBaseAdapter(
            new NavDrawerAdapter(this, R.layout.navdrawer_item, menu ));
        return navDrawerActivityConfiguration;
    }

	
	/*
	 * Provides callbacks that are called when the client is connected or disconnected from the service. 
	 * Most applications implement onConnected(Bundle) to start making requests.
	 * implements GooglePlayServicesClient.ConnectionCallbacks
	 */
	@Override
	public void onConnected(Bundle arg0) {
		mCurrentLocation = mLocationClient.getLastLocation();
		SharedPreferences prefs = getSharedPreferences("PREF", MODE_PRIVATE);
		if(prefs.getBoolean("isRadiusChanged", false)){
			SharedPreferences.Editor editor = prefs.edit();
			editor.putBoolean("isRadiusChanged", false);
			editor.commit();
			// make sure list updates
			reloadAll();
		}
	}

	@Override
	public void onDisconnected() {}
	
	/*
	 * Function of the List Fragments interface 
	 */
	// Gets a lat and long and returns the distance from the user's current location
	public double calculateDistanceFromCurrentLocationInMiles(double lat1, double lng1) {
		double lat2, lng2;
		if(mCurrentLocation != null){
			lat2 = mCurrentLocation.getLatitude();
			lng2 = mCurrentLocation.getLongitude();
		}else{
			// if current location is null check if we got a valid last known location from the SplashscreenActivity
			Bundle locationBundle = getIntent().getExtras();
			if(locationBundle != null && locationBundle.getDouble("lat", 0) != 0){
				lat2 = locationBundle.getDouble("lat", 0);
				lng2 = locationBundle.getDouble("lng", 0);
			// if all has failed, just return 0
			} else{
				return 0;
			}
		}
	    double earthRadius = 3958.75;
		double dLat = Math.toRadians(lat2-lat1);
		double dLng = Math.toRadians(lng2-lng1);
	    double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng/2) * Math.sin(dLng/2);
	    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
	    double dist = earthRadius * c;
	    return dist;
	}
	
	public void notifyPagerAdapterDataSetChanged(){
		mPlaceListPagerAdapter.notifyDataSetChanged();
	}

	
///////////////////// Places list handling methods //////////////////////////////////
	
	/* Called when the user clicked the reload actionbar item
     * Uses an Async task to reload all of the places from the server
     */
    protected void reloadAll(){
    	new AsyncTask<Void, Void, Void>(){

			@Override
			protected void onPreExecute() {
				showProgressCircle();
			}

			@Override
			protected Void doInBackground(Void... params) {
				int currRadius = getCurrRadiusToLoad();
				if(mCurrentLocation != null){
					Places.getInitializedInstance(mCurrentLocation, currRadius);
					// gets the friend's places list from the singlton
					FBFriendTabFragment.places = Places.getInstance().filterPlacesByFriends();
				}else{
					LocationRequest mLocationRequest = LocationRequest.create();
			        // Use high accuracy
			        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
			        mLocationRequest.setInterval(5000);
			        // Set the request for only one updates
			        mLocationRequest.setNumUpdates(1);
			        // Make an update request for one accurate current location
					mLocationClient.requestLocationUpdates(mLocationRequest, HomeActivity.this);
				}
				return null;
			}

			@Override
			protected void onPostExecute(Void result) {
				// update all adapters
				if(mLocationClient.getLastLocation() != null){
					if(FBFriendTabFragment.adapter != null)
						FBFriendTabFragment.adapter.notifyDataSetChanged();
					mPlaceListPagerAdapter.notifyDataSetChanged();
					hideProgressCircle();
				}
			}
			
    	}.execute();
    }
    
    // returns the current radius in km (if settings set to miles, converts to km)
    private int getCurrRadiusToLoad(){
    	SharedPreferences pref = getSharedPreferences("PREF", 0);
    	int currRadius = pref.getInt("radius", 20);
    	// if radius is in miles, convert it to km
		if(!pref.getBoolean("isKm", true))
			currRadius *= 1.6;
		return currRadius;
    }
}
